package a02;

import java.io.Serializable;

public abstract class AbstractRegularGame<M> implements RegularGame<M>,
	Cloneable, Serializable {
    private static final long serialVersionUID = 1L;
    protected final static byte NONE = 0;
    protected final static byte ONE = 1;
    protected final static byte TWO = 22;

    private byte[][] b;

    private byte columns;

    private byte lastColumn = -1;
    private byte lastRow = -1;
    private int movesDone = 0;
    private byte player = getOne();
    private byte rows;
    private Boolean winsLast = null;

    public AbstractRegularGame(byte c, byte r) {
	this.columns = c;
	this.rows = r;
	this.setB(new byte[this.getColumns()][]);
	for (int i = 0; i < this.getColumns(); i++) {
	    this.getB()[i] = new byte[this.getRows()];
	}
    }

    public static byte getNone() {
	return NONE;
    }

    public static byte getOne() {
	return ONE;
    }

    public static byte getTwo() {
	return TWO;
    }

    @Override
    public AbstractRegularGame<?> clone() {

	AbstractRegularGame<?> result = null;

	try {
	    result = (AbstractRegularGame<?>) super.clone();

	    result.setB(this.getB().clone());
	    result.winsLast = null;

	    for (int i = 0; i < result.getB().length; i++) {
		result.getB()[i] = result.getB()[i].clone();
	    }

	} catch (CloneNotSupportedException _) {
	}

	return result;
    }

    @Override
    public byte currentPlayer() {
	return this.getPlayer();
    }

    @Override
    public boolean ended() {
	return this.noMoreMove() || this.wins();
    }

    @Override
    public byte getAtPosition(byte column, byte row) {
	return this.getB()[column][row];
    }

    public byte[][] getB() {
	return this.b;
    }
    
   



    @Override
    public int getColumns() {
	return this.columns;
    }

    public int getMovesDone() {
	return this.movesDone;
    }

    public byte getPlayer() {
	return this.player;
    }

    @Override
    public byte getPlayerNone() {
	return getNone();
    }

    @Override
    public byte getPlayerOne() {
	return getOne();
    }

    @Override
    public byte getPlayerTwo() {
	return getTwo();
    }

    @Override
    public int getRows() {
	return this.rows;
    }

    public byte lastPlayer() {
	return this.otherPlayer(this.getPlayer());
    }

    public byte nextPlayer() {
	return this.otherPlayer(this.getPlayer());
    }

    @Override
    public byte otherPlayer(byte p) {
	return p == getOne() ? getTwo() : getOne();
    }

    public void setB(byte[][] b) {
	this.b = b;
    }

    public void setMovesDone(int movesDone) {
	this.movesDone = movesDone;
    }

    public void setPlayer(byte player) {
	this.player = player;
    }

    public boolean wins() {
	if (this.winsLast == null) {
	    this.winsLast = this.wins(this.lastPlayer());
	}
	return this.winsLast;
    }

    public byte getLastColumn() {
	return lastColumn;
    }

    public void setLastColumn(byte lastColumn) {
	this.lastColumn = lastColumn;
    }

    public byte getLastRow() {
	return lastRow;
    }

    public void setLastRow(byte lastRow) {
	this.lastRow = lastRow;
    }

}
